.. _Видимость имени:

Видимость имени (Область действия имени)
========================================

.. index::
    область действия имени


Любое имя доступно от точки, где оно было определено, до точки,
где заканчивается его область действия (блок кода, функция, класс и т.д.), а также во всех областях, которые включает его область действия. В
связи с этим каждая область определяет область действия имени. Имена недоступны за пределами их области действия:


.. code-block:: d

    void main()
    { //открывает область видимости
        int outer;
        if (aCondition)
        { // фигурная скобка открывает новую область видимости
            int inner = 1;
            outer = 2; // ← 'outer' доступна здесь
        } // ← 'inner' недоступно за пределами этой области
        inner = 3; //  ошибка компиляции
        //'inner' недоступна за пределами этой области
    }



Поскольку переменная inner определена внутри области ограниченной фигурными скобками оператора if и следовательно доступна
только в этой области. С другой стороны переменная outer доступна везде, внутри функции.
Недопустимо определять еще одну переменную с тем же именем, что и переменная во внешней области действия

.. code-block:: d

    size_t length = oddNumbers.length;
    if (aCondition)
    {
        size_t length = primeNumbers.length; // ошибка компиляции
    }


Область действия не обязательно должна быть ассоциированаться с оператором. Область действия может быть определена
свободной парой фигурных скобок внутри функции (или другой конструкции (класс, например))


.. code-block:: d

    void main()
    {
        // This scope is not associated with any statement:
        {
            int a;
        }
        //  Another one:
        {
            int a;      // This 'a' is different from the previous one
        }
    }


Однако такие несвязанные области не могут быть определены в области модуля (на верхнем
уровне исходного кода).:

.. code-block:: d

    void main()
    {
        // ...
    }
    {
    }  // ошибка компиляции



Определение имени должно быть как можно ближе к месту её первого использования
------------------------------------------------------------------------------

Как мы видели в предыдущих программах, переменная должна быть определена перед первым использованием

.. code-block:: d

    writeln(number);
    int number = 42;  // ошибка компиляции: number is not known yet


Чтобы этот код был приемлем для компилятора, number должен быть определен до того, как он будет
использоваться с written . Хотя нет ограничений на то, за сколько строк до этого он
должен быть определен, хорошей практикой программирования считается
определение переменных ближе всего к месту их первого использования.
Давайте посмотрим на это в программе, которая выводит среднее значение чисел, полученных
от пользователя. Программисты, имеющие опыт работы с некоторыми другими
языками программирования, знают что переменные могут быть определены в облегающих областяхвидимости

.. code-block:: d

    int count;
    int[] numbers;
    double averageValue;
    write("How many numbers are there? ");
    readf(" %s",  & count);
    if (count >= 1)
    {
        numbers.length = count;
        // ... предположим вычисления прходят здесь
    }
    else
    {
        writeln("ERROR: You must enter at least one number!");
    }

Сравните приведенный выше код с приведенным ниже, который определяет переменные позже, там где каждая
переменная фактически начинает принимать участие в программе:

.. code-block:: d

    write("How many numbers are there? ");
    int count;
    readf(" %s",  & count);
    if (count >= 1)
    {
        int[] numbers;
        numbers.length = count;
        double averageValue;
        // ... предположим вычисления прходят здесь
    }
    else
    {
        writeln("ERROR: You must enter at least one number!");
    }


Хотя определение всех переменных вверху может выглядеть структурно лучше,
есть несколько преимуществ определения их как можно позже:

* Скорость: Каждое определение переменной, как правило, увеличивает скорость работы
  программы. Поскольку каждая переменная инициализируется в D, определение переменных вверху
  приведет к тому, что они всегда будут инициализированы, даже если они будут использоваться
  позже только иногда, что приведет к потере ресурсов.
* Риск ошибок: Каждая строка между определением переменной и ее использованием
  сопряжена с повышенным риском ошибок программирования. В качестве примера
  рассмотрим переменную с общим именем length . Можно перепутать
  эту переменную с какой-либо другой длиной и использовать ее непреднамеренно, не достигнув
  строка ее первого предполагаемого использования. Когда эта строка, наконец, будет достигнута, переменная
  может больше не иметь желаемого значения.
* Удобочитаемость: По мере увеличения количества строк в области видимости возрастает вероятность
  того, что определение переменной находится слишком высоко в исходном коде, что вынуждает
  программиста прокручивать страницу назад, чтобы посмотреть на ее определение.
* Поддержка кода: Исходный код постоянно модифицируется и
  совершенствуется: добавляются новые функции, удаляются старые,
  исправляются ошибки и т.д. Эти изменения иногда приводят к необходимости полностью извлечь группу
  строк в новую функцию.
  Когда это происходит, наличие всех переменных, определенных близко к строкам, которые их используют, облегчает перемещение их как связной группы.
  Например, в последнем приведенном выше коде, который следовал этому руководству, все
  строки внутри инструкции if могут быть перемещены в новую функцию в программе.
  С другой стороны, когда переменные всегда определены вверху, если какие
  -то строки когда-либо потребуется переместить, переменные, которые используются в этих строках, должны быть
  идентифицированы одна за другой.

